package com.itheima.reggie.controller;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.github.wxpay.sdk.MyConfig;
import com.github.wxpay.sdk.WXPay;
import com.github.wxpay.sdk.WXPayUtil;
import com.itheima.reggie.common.BaseContext;
import com.itheima.reggie.common.R;
import com.itheima.reggie.entity.*;
import com.itheima.reggie.service.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

/**
 * 订单
 */
@Slf4j
@RestController
@RequestMapping("/order")
public class OrderController {
    @Autowired
    private OrderService orderService;

    @Autowired
    private ShoppingCartService shoppingCartService;

    @Autowired
    private AddressBookService addressBookService;

    @Autowired
    private UserService userService;

    /**
     * 用户下单
     * @param orders
     * @return
     */
    @PostMapping("/submit")
    public R submit(@RequestBody Orders orders){
        //A. 获得当前用户id, 查询当前用户的购物车数据
        Long userId = BaseContext.getCurrentId();
        User user = userService.getById(userId);

        //商品明细，可以从购物车中直接获取
        LambdaQueryWrapper<ShoppingCart> wapper = new LambdaQueryWrapper<>();
        wapper.eq(ShoppingCart::getUserId,userId);
        List<ShoppingCart> shoppingCarts = shoppingCartService.list(wapper);
        if(shoppingCarts == null || shoppingCarts.size() == 0){
            return R.error("购物车为空，不能下单");
        }
        //B. 根据当前登录用户id, 查询用户数据

        //C. 根据地址ID, 查询地址数据
        Long addressBookId = orders.getAddressBookId();
        AddressBook addressBook = addressBookService.getById(addressBookId);
        if(addressBook == null){
            return R.error("请选择地址");
        }
        //D. 封装订单数据，然后存储
        long orderId = IdWorker.getId();//订单号
        //存储订单的总金额
        AtomicInteger amount = new AtomicInteger(0);
        //组装订单明细信息
        List<OrderDetail> orderDetails = shoppingCarts.stream().map((item) -> {
            OrderDetail orderDetail = new OrderDetail();
            orderDetail.setOrderId(orderId);
            orderDetail.setNumber(item.getNumber());
            orderDetail.setDishFlavor(item.getDishFlavor());
            orderDetail.setDishId(item.getDishId());
            orderDetail.setSetmealId(item.getSetmealId());
            orderDetail.setName(item.getName());
            orderDetail.setImage(item.getImage());
            orderDetail.setAmount(item.getAmount());
            amount.addAndGet(item.getAmount().multiply(new BigDecimal(item.getNumber())).intValue());
            return orderDetail;
        }).collect(Collectors.toList());


        //组装订单数据
        orders.setId(orderId);
        orders.setOrderTime(LocalDateTime.now());
        orders.setCheckoutTime(LocalDateTime.now());
        orders.setStatus(1);
        orders.setAmount(new BigDecimal(amount.get()));//总金额
        orders.setUserId(userId);
        orders.setNumber(String.valueOf(orderId));
        orders.setUserName(user.getName());
        orders.setConsignee(addressBook.getConsignee());
        orders.setPhone(addressBook.getPhone());
        orders.setAddress((addressBook.getProvinceName() == null ? "" : addressBook.getProvinceName())
                + (addressBook.getCityName() == null ? "" : addressBook.getCityName())
                + (addressBook.getDistrictName() == null ? "" : addressBook.getDistrictName())
                + (addressBook.getDetail() == null ? "" : addressBook.getDetail()));
        //向订单表插入数据，一条数据
        orderService.save(orders);

        //E. 封装订单明细数组，然后存储
        orderDetailService.saveBatch(orderDetails);

        //F. 清空用户的购物车
        shoppingCartService.remove(wapper);


        //G.提交微信生成支付二维码
        Map<String, String> responseMap = null;
        try {
            responseMap = createOrderWx(orders.getId(), orders.getAmount().intValue()*100, orders.getUserName());

        } catch (Exception e) {
            e.printStackTrace();
        }
        return R.success(responseMap);
    }

    @Autowired
    private OrderDetailService orderDetailService;


    private Map<String,String> createOrderWx(Long orderId,int price,String body) throws Exception {
        //1.创建wx配置赌侠昂
        MyConfig myConfig = new MyConfig();
        //2.创建wx支付核心对象
        WXPay wxPay = new WXPay(myConfig);
        //3.使用wxPay 来执行下单功能
        Map<String, String> requsetMap = new HashMap<>();
        //购买的商品信息
        requsetMap.put("body", "传智播客");
        //商家的订单号
        requsetMap.put("out_trade_no",orderId+"");
        //付款金额
        requsetMap.put("total_fee",price+"");//以分为单位

        requsetMap.put("spbill_create_ip","127.0.0.1");
        //回调通知  商家接收微信的信息的接口
        //公网的服务器接口
        requsetMap.put("notify_url","http://32633x11x9.zicp.vip/order/notifyAll");
        //支付类型
        requsetMap.put("trade_type","NATIVE");

        Map<String, String> responseMap = wxPay.unifiedOrder(requsetMap);

        responseMap.put("out_trade_no",orderId+"");

        return responseMap;
    }

    /**
     * 条件 ： /notify 微信能访问才可以。  公网地址
     */
    @RequestMapping("/notifyAll")
    public void notifyOfWx(HttpServletRequest request, HttpServletResponse response){
        //触发描述
        System.out.println("支付成功回调。。。。");
        try {
            //输入流转换为xml字符串
            String xml = convertToString( request.getInputStream() );
            System.out.println(xml);
            //把xml 转换城一个Map集合
            Map<String, String> map = WXPayUtil.xmlToMap(xml);

            //获得是否成功的信息SUCCESS
            String result_code = map.get("result_code");
            if(!result_code.equals("SUCCESS")){
                throw new RuntimeException("支付失败，进行人工处理");
            }
            //返回值中有连个属性，最为重要
            //商家订单号。 根据订单号来修改数据库中订单的支付状态
            String out_trade_no = map.get("out_trade_no");

            //微信流水号 记录微信的支付凭证
            String transaction_id = map.get("transaction_id");

            //根据订单号，查询订单数据，
            Orders order = orderService.getById(out_trade_no);

            //修改支付状态为已支付
            order.setStatus(2);
            //更新数据库数据即可
            orderService.updateById(order);
            //需要更新微信调用的信息，来修改订单的状态为已支付
            //给微信支付一个成功的响应
            response.setContentType("text/xml");
            String data = "<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>";
            response.getWriter().write(data);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    /**
     * 输入流转换为xml字符串
     * @param inputStream
     * @return
     */
    public static String convertToString(InputStream inputStream) throws
            IOException {
        ByteArrayOutputStream outSteam = new ByteArrayOutputStream();
        byte[] buffer = new byte[1024];
        int len = 0;
        while ((len = inputStream.read(buffer)) != -1) {
            outSteam.write(buffer, 0, len);
        }
        outSteam.close();
        inputStream.close();
        String result = new String(outSteam.toByteArray(), "utf-8");
        return result;
    }



    //查询订单的状态信息
    @GetMapping("/findStatusById")
    public R findStatusById(String orderId){

        //1.根据Id查询订单状态
        Orders order = orderService.getById(orderId);

        //2.判断状态是否为2
        if(order.getStatus() == 2){

            return R.success("支付成功");//code = 1
        }
        //3.如果状态为已支付。直接跳转 返回code 1
        return R.error("等待支付"); //code = 0

    }
}